package com.bookmanger.server.service.impl;

import com.bookmanger.common.result.Result;
import com.bookmanger.pojo.DTO.BorrowDTO;
import com.bookmanger.pojo.Entity.*;
import com.bookmanger.pojo.VO.BorrowBook4ManagerVO;
import com.bookmanger.server.mapper.BookMapper;
import com.bookmanger.server.mapper.BorrowMapper;
import com.bookmanger.server.mapper.IsbnMapper;
import com.bookmanger.server.mapper.ReadersMapper;
import com.bookmanger.server.mapper.ReaderTypeMapper;
import com.bookmanger.server.service.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;

@Service
public class BorrowServiceImpl implements BorrowService {

    @Autowired
    private BorrowMapper borrowMapper;
    @Autowired
    private IsbnMapper isbnMapper;
    @Autowired
    private BookMapper bookMapper;
    @Autowired
    private ReadersMapper readerMapper;
    @Autowired
    private FineService fineService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private PreBookService prebookService;
    @Autowired
    private ReaderTypeMapper readerTypeMapper;
    @Autowired
    private RankingService rankingService;


    private static final BigDecimal OVERDUE_FINE_PER_DAY = new BigDecimal("0.5");
    private static final String OVERDUE_REASON = "图书逾期未还";
    private static final String DAMAGE_OR_LOST_REASON = "图书损坏或丢失";

    @Override
    @Transactional
    public Integer borrowBook(Integer readerId, Integer bookId, LocalDateTime informTime) {
        // 检查读者是否存在
        ReaderEntity reader = readerMapper.findById(readerId);
        if (reader == null) {
            return null;
        }

        // 获取图书信息
        BookEntity bookEntity = bookMapper.selectById(bookId);
        if (bookEntity == null) {
            return null;
        }

        // 检查ISBN是否存在
        IsbnEntity isbn = isbnMapper.selectById(bookEntity.getIsbnId());
        if (isbn == null) {
            return null;
        }

        // 检查读者是否已达最大借书数
        Integer maxBooks = readerTypeMapper.getMaxBooksByReaderId(readerId);
        if (maxBooks == null) {
            maxBooks = 10; // 默认值
        }
        if (reader.getBorrowedNumber() >= maxBooks) {
            return null;
        }

        // 创建借阅DTO
        BorrowDTO borrowDTO = new BorrowDTO();
        borrowDTO.setReaderId(readerId);
        borrowDTO.setIsbnId(bookEntity.getIsbnId());
        borrowDTO.setBookId(bookId);
        
        // 使用informTime作为借阅时间
        borrowDTO.setBorrowTime(informTime);
        
        // 计算应还日期（根据读者类型和图书类型从borrow_limit表获取借阅天数）
        Integer borrowDays = readerTypeMapper.getBorrowDaysByReaderIdAndBookTypeId(
                readerId, isbn.getTypeId());
        if (borrowDays == null) {
            borrowDays = 30; // 默认借阅天数
        }
        borrowDTO.setDueTime(borrowDTO.getBorrowTime().plusDays(borrowDays));

        // 插入借阅记录
        int borrowResult = borrowMapper.insertBorrowRecord(borrowDTO);
        if (borrowResult > 0) {
            return borrowDTO.getId(); // 返回插入记录的ID
        }
        return null;
    }

    @Override
    @Transactional
    public boolean borrowBook(BorrowDTO borrowDTO) {

        // 检查读者是否存在
        ReaderEntity reader = readerMapper.findById(borrowDTO.getReaderId());
        if (reader == null) {
            return false;
        }

        // 检查ISBN是否存在
        IsbnEntity isbn = isbnMapper.selectById(borrowDTO.getIsbnId());
        if (isbn == null) {
            return false;
        }
        if (isbn.getStock()==0){
            return false;
        }
        // 检查读者是否已达最大借书数
        Integer maxBooks = readerTypeMapper.getMaxBooksByReaderId(borrowDTO.getReaderId());
        if (maxBooks == null) {
            maxBooks = 10; // 默认值
        }
        if (reader.getBorrowedNumber() >= maxBooks) {
            return false;
        }

        // 查找可用的图书实体（未被借出且未被挂失）
//        BookEntity bookEntity = bookMapper.findAvailableBookByIsbnId(borrowDTO.getIsbnId());
//        if (bookEntity == null) {
//            return false;
//        }

        // 设置借阅时间

        // 设置borrowTime为当日的24:00
        LocalDateTime todayEnd = LocalDate.now().atTime(23, 59, 59);
        borrowDTO.setBorrowTime(todayEnd);
        
        // 计算应还日期（根据读者类型和图书类型从borrow_limit表获取借阅天数）
        Integer borrowDays = readerTypeMapper.getBorrowDaysByReaderIdAndBookTypeId(
                borrowDTO.getReaderId(), isbn.getTypeId());
        if (borrowDays == null) {
            borrowDays = 30; // 默认借阅天数
        }
        borrowDTO.setDueTime(borrowDTO.getBorrowTime().plusDays(borrowDays));

        // 设置图书ID
//        borrowDTO.setBookId(bookEntity.getId());
        
        // 仅插入借阅记录，不更新库存和读者借阅数，这些将在审批时处理
        int borrowResult = borrowMapper.insertBorrowRecord(borrowDTO);
        return borrowResult > 0;
    }

    @Override
    @Transactional
    public Result approveBorrow(Integer borrowId, Integer managerId) {
        // 管理员批准借阅
        BorrowEntity borrowRecord = borrowMapper.findById(borrowId);
        if (borrowRecord == null || borrowRecord.getBorrowManagerId() != null) {
            return Result.error("借阅记录不存在或已处理");
        }
        BookEntity bookEntity = bookMapper.findAvailableBookByIsbnId(borrowRecord.getIsbnId());
        if (bookEntity == null) {
            return Result.error("该书已无库存");
        }

        // 更新借阅管理员ID
        if (borrowMapper.updateBorrowManagerId(borrowId, managerId,bookEntity.getId()) <= 0) {
            return Result.error("更新借阅记录失败");
        }
        borrowRecord = borrowMapper.findById(borrowId);
        IsbnEntity isbn = isbnMapper.selectById(borrowRecord.getIsbnId());


        if(isbn.getStock()==0){
            return Result.error("该书已无库存");
        }
        // 更新库存和读者借阅数
        if (isbnMapper.updateStock(borrowRecord.getIsbnId(), -1) <= 0) {
            return Result.error("更新ISBN库存失败");
        }
        readerMapper.updateBorrowedNumber(borrowRecord.getReaderId(), 1);
        
        // 将书籍的is_pass设置为1，表示已借出
        bookMapper.updateBookPassStatus(borrowRecord.getBookId(), 1);
        rankingService.updateSet(borrowId);
        return Result.success("审批成功");
    }

    @Override
    @Transactional
    public boolean returnBook(Integer borrowId) {
        BorrowEntity borrowRecord = borrowMapper.findById(borrowId);
        if (borrowRecord == null || borrowRecord.getReturnTime() != null) {
            return false;
        }

        // 仅标记为请求归还，实际处理在审批中完成
        return true;
    }

    @Override
    @Transactional
    public boolean approveReturnBook(Integer borrowId, Integer managerId) {
        // 管理员批准还书
        BorrowEntity borrowRecord = borrowMapper.findById(borrowId);
        if (borrowRecord == null || borrowRecord.getReturnTime() != null || borrowRecord.getReturnManagerId() != null) {
            return false;
        }

        LocalDate dueDate = borrowRecord.getDueTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate returnDate = LocalDate.now();

        if (returnDate.isAfter(dueDate)) {
            long overdueDays = ChronoUnit.DAYS.between(dueDate, returnDate);
            BigDecimal fineAmount = OVERDUE_FINE_PER_DAY.multiply(new BigDecimal(overdueDays));

            PunishmentEntity fine = new PunishmentEntity();
            fine.setReaderId(borrowRecord.getReaderId());
            fine.setBookId(borrowRecord.getBookId());
            fine.setPunNum(fineAmount);
            fine.setPunCause(OVERDUE_REASON);
            fineService.recordFine(fine);

            // 发送逾期罚款通知邮件
            String readerEmail = readerMapper.findEmailById(borrowRecord.getReaderId());
            if (readerEmail != null) {
                String subject = "图书逾期罚款通知";
                String content = String.format("您借阅的图书已逾期%d天，需缴纳罚款%.2f元。", overdueDays, fineAmount);
                emailService.sendEmail(readerEmail, subject, content);
            }
        }

        // 更新归还时间和管理员ID
        if (borrowMapper.updateReturnManagerId(borrowId, managerId) <= 0) {
            return false;
        }
        
        if (borrowMapper.updateReturnTime(borrowId) > 0) {
            prebookService.processPreBook(borrowRecord.getBookId());
            readerMapper.updateBorrowedNumber(borrowRecord.getReaderId(), -1);
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean handleDamagedOrLostBook(Integer borrowId, String damageOrLostCause) {
        BorrowEntity borrowRecord = borrowMapper.findById(borrowId);
        if (borrowRecord == null || borrowRecord.getReturnTime() != null) {
            return false;
        }
        BigDecimal fineAmount = new BigDecimal("50.00");

        PunishmentEntity fine = new PunishmentEntity();
        fine.setReaderId(borrowRecord.getReaderId());
        fine.setBookId(borrowRecord.getBookId());
        fine.setPunNum(fineAmount);
        fine.setPunCause(DAMAGE_OR_LOST_REASON + ": " + damageOrLostCause);
        fineService.recordFine(fine);

        // 发送图书损坏/丢失罚款通知邮件
        String readerEmail = readerMapper.findEmailById(borrowRecord.getReaderId());
        if (readerEmail != null) {
            String subject = "图书损坏/丢失罚款通知";
            String content = String.format("您借阅的图书因%s，需缴纳罚款%.2f元。", damageOrLostCause, fineAmount);
            emailService.sendEmail(readerEmail, subject, content);
        }

        borrowMapper.markAsHandled(borrowId);

        return true;
    }
    
    @Override
    public PageInfo<BorrowEntity> getPendingBorrowApplications(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowEntity> borrowEntities = borrowMapper.findPendingBorrowApplications();
        return new PageInfo<>(borrowEntities);
    }

    @Override
    public PageInfo<BorrowEntity> getApprovedBorrowApplications(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowEntity> borrowEntities = borrowMapper.findApprovedBorrowApplications();
        return new PageInfo<>(borrowEntities);
    }

    @Override
    public PageInfo<BorrowEntity> getPendingReturnApplications(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowEntity> borrowEntities = borrowMapper.findPendingReturnApplications();
        return new PageInfo<>(borrowEntities);
    }

    @Override
    public PageInfo<BorrowEntity> getApprovedReturnApplications(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowEntity> borrowEntities = borrowMapper.findApprovedReturnApplications();
        return new PageInfo<>(borrowEntities);
    }
    
    @Override
    public PageInfo<BorrowBook4ManagerVO> getPendingBorrowApplicationsWithDetails(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowBook4ManagerVO> borrowEntities = borrowMapper.findPendingBorrowApplicationsWithDetails();
        return new PageInfo<>(borrowEntities);
    }
    
    @Override
    public PageInfo<BorrowBook4ManagerVO> getApprovedBorrowApplicationsWithDetails(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowBook4ManagerVO> borrowEntities = borrowMapper.findApprovedBorrowApplicationsWithDetails();
        return new PageInfo<>(borrowEntities);
    }
    
    @Override
    public PageInfo<BorrowBook4ManagerVO> getPendingReturnApplicationsWithDetails(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowBook4ManagerVO> borrowEntities = borrowMapper.findPendingReturnApplicationsWithDetails();
        return new PageInfo<>(borrowEntities);
    }
    
    @Override
    public PageInfo<BorrowBook4ManagerVO> getApprovedReturnApplicationsWithDetails(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowBook4ManagerVO> borrowEntities = borrowMapper.findApprovedReturnApplicationsWithDetails();
        return new PageInfo<>(borrowEntities);
    }
    
    @Override
    public PageInfo<BorrowBook4ManagerVO> getBorrowRecordsByUserIdOrName(String keyword, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize, true);
        List<BorrowBook4ManagerVO> borrowRecords = borrowMapper.findBorrowRecordsByUserIdOrName(keyword);
        return new PageInfo<>(borrowRecords);
    }
}